jsq.Class=function(define) {
	for(var clsName in define) {
		var cls=define[clsName];
		var retObj=function() {
		    if (arguments.length==50 && arguments[49]==2&& arguments[0]==1) return;
			if (this._swaf_event_map_define && swaf.message) {
			    if (this.EVENT_SRC) {
			        if (typeof this.EVENT_SRC == 'string') swaf.event(swaf.$(this.EVENT_SRC),this._swaf_event_map_define);
			        else if (this.EVENT_SRC instanceof RegExp) swaf.event(swaf.$(this.EVENT_SRC),this._swaf_event_map_define);
			        else swaf.event(this.EVENT_SRC,this._swaf_event_map_define);
			    }
				else swaf.event(this,this._swaf_event_map_define);
			}
			for(var i=0;i<this._inherit_initList.length;i++) {
					this[this._inherit_initList[i]].apply(this,arguments);
			}
			if (this.init) this.init.apply(this,arguments);
		};
	    if (cls.BASE) {
	        var baseCls=null;
	        if (cls.BASE instanceof Array) baseCls=cls.BASE[0];
	        else baseCls=cls.BASE;
	        retObj.prototype=new baseCls(1,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,2);
            baseCls=null;                            
        }
		for(var property in cls) {retObj.prototype[property]=cls[property];}
		retObj.prototype.CLASSNAME=cls.NAMESPACE?cls.NAMESPACE.NAMESPACE+'.'+clsName:clsName;
		if (!cls.BASE) cls.BASE=swaf.dummy._swaf_base_class;
		// process extend
		{
			var extList=cls.BASE;
			if (extList instanceof Array && extList.length>1) {
				for(var i=0;i<extList.length;i++) {
					swaf.dummy._swaf_process_class_inherit(retObj,extList[i]);
				}
			} else {
				swaf.dummy._swaf_process_class_inherit(retObj,extList);
			}
			delete cls.BASE;
		}
		if (cls.EXTEND) {
			var extList=cls.EXTEND;
			if (extList instanceof Array && extList.length>1) {
				for(var i=0;i<extList.length;i++) {
					swaf.dummy._swaf_process_class_extend(retObj,extList[i]);
				}
			} else {
				swaf.dummy._swaf_process_class_extend(retObj,extList);
			}
			delete cls.EXTEND;
		}
		if (cls.EVENT_MAP && swaf.message) {
			retObj.prototype._swaf_event_map_define={};
			for(var msg in cls.EVENT_MAP) {
				var item=cls.EVENT_MAP[msg];
				if (item instanceof Array) {
					retObj.prototype._swaf_event_map_define[msg]=[];
					for(var i=0;i<item.length;i++) {
						retObj.prototype._swaf_event_map_define[msg].push(retObj.prototype[item]);
					}
				} else {
					retObj.prototype._swaf_event_map_define[msg]=retObj.prototype[item];
				}
				item=null;
			}
			delete cls.EVENT_MAP;
		}

		retObj.prototype.toString=function() {return this.CLASSNAME;};

	    var singletonObj=null;
		if (typeof cls.SINGLETON !='undefined') {
		    if (cls.SINGLETON==true) {
		        singletonObj={scope:'page',lazyInit:false};
		    } else if (typeof cls.SINGLETON == 'object') { singletonObj=cls.SINGLETON;}
		    if (singletonObj) {
		        retObj.prototype._singleton_info=singletonObj;
		    }
		    delete cls.SINGLETON;
		}

		if (cls.NAMESPACE) {
			cls.NAMESPACE[clsName]=retObj;
			delete cls.NAMESPACE;
		} else {
			window[clsName]=retObj;
		}
		
        if (singletonObj && singletonObj.lazyInit==false) swaf.factory.get(retObj.prototype.CLASSNAME);
		
		retObj=null;
	}
};

/////////////////////////// singleton factory ////////////////////////////
swaf.factory={_repository:{},_referenceCounter:{}};
swaf.factory.get=function(classname) {
    if (typeof classname=='function' && classname.prototype.CLASSNAME) classname=classname.prototype.CLASSNAME;
    var info=classname.toObject().prototype._singleton_info;
    if (info) {
        var scope=info.scope;
        if (scope=='domain') {
            var respository=swaf.gs('_swaf_factory_repository');
            if (!respository[classname]) {
                eval('var instance=new '+classname);
                instance.isSingleton=true;
                respository[classname]=instance;
            }
            if (swaf.factory._referenceCounter[classname]) swaf.factory._referenceCounter[classname]++;
            else swaf.factory._referenceCounter[classname]=1;
            var reference=swaf.gs('_swaf_factory_referenceCounter');
            if (reference[classname]) reference[classname]++;
            else reference[classname]=1;
            return respository[classname];
        } else {
            if (!swaf.factory._repository[classname]) {
                eval('var instance=new '+classname);
                instance.isSingleton=true;
                swaf.factory._repository[classname]=instance;
            }
            return swaf.factory._repository[classname];
        }
    }
    return null;
};

swaf.factory.regist=function(classDefine,info) {
    if (!info) info={scope:'page',lazyInit:false};
    classDefine.prototype._singleton_info=info;
    var ret=swaf.factory.get(classDefine.prototype.CLASSNAME);
    return ret;
};

swaf.factory.remove=function(classname) {
    if (typeof classname=='function' && classname.prototype.CLASSNAME) classname=classname.prototype.CLASSNAME;
    var scope=classname.toObject().prototype._singleton_info.scope;
    if (scope=='domain') {
        var respository=swaf.gs('_swaf_factory_repository');
        respository[classname]=null;
        swaf.factory._referenceCounter[classname]--;
        var reference=swaf.gs('_swaf_factory_referenceCounter');
        reference[classname]--;
    } else {
        swaf.factory._repository[classname]=null;
    }
};

swaf.factory.unloadPage=function() {
    var reference=swaf.gs('_swaf_factory_referenceCounter');
    for(var classname in swaf.factory._referenceCounter) {
        reference[classname]-=swaf.factory._referenceCounter[classname];
        if (reference[classname]<=0) {
            var respository=swaf.gs('_swaf_factory_repository');
            delete respository[classname];
            delete reference[classname];
        }
    }
};

/////////////////////////// class ////////////////////////////
swaf.dummy._swaf_base_class=function() {};
swaf.dummy._swaf_base_class.prototype={
	CLASSNAME : 'base',
	_inherit_initList:[],
	_inherit_list:['base'],
	isSwafClass:true,
	isSingleton:false,
	init : function() {
	},
	instanceOf:function(cls) {
	    return (this._inherit_list.find(cls.prototype.CLASSNAME)>=0);
	}
};

swaf.dummy._swaf_class_keyword='parent|BASE|EXTEND|NAMESPACE';
swaf.dummy._swaf_class_regexp=/\./g;

swaf.dummy._swaf_process_class_inherit=function(child,parent) {
    /* 20071121 buld inherit list for instanceOf - reizes*/
    child.prototype._inherit_list=parent.prototype._inherit_list;
    child.prototype._inherit_list.push(child.prototype.CLASSNAME);
	for(var property in parent.prototype) {
		if (swaf.dummy._swaf_class_keyword.indexOf(property)>=0) continue;
		if (property=='EVENT_MAP') {
			if (!child.prototype.EVENT_MAP) child.prototype.EVENT_MAP={};
			$extend(child.prototype.EVENT_MAP,parent.prototype.EVENT_MAP);
		} else {
			if (child.prototype[property]) {
			    var arrclsname=parent.prototype.CLASSNAME.split('.');
				var clsname=parent.prototype.CLASSNAME.replace(swaf.dummy._swaf_class_regexp,'_');
				child.prototype['parent$'+property]=parent.prototype[property];
				child.prototype[clsname+'$'+property]=parent.prototype[property];
				if (arrclsname.length>1) child.prototype[arrclsname.last()+'$'+property]=parent.prototype[property];
				if (property=='init') {
					var tmp=parent.prototype._inherit_initList.concat([clsname+'$'+property]);
					if (child.prototype._inherit_initList) child.prototype._inherit_initList=child.prototype._inherit_initList.concat(tmp);
					else child.prototype._inherit_initList=tmp;
				}
			} else {
				child.prototype[property]=parent.prototype[property];
				if (property=='init') {
					var tmp=parent.prototype._inherit_initList.concat([property]);
					if (child.prototype._inherit_initList) child.prototype._inherit_initList=child.prototype._inherit_initList.concat(tmp);
					else child.prototype._inherit_initList=tmp;
				}
			}
		}
	}
};
swaf.dummy._swaf_process_class_extend=function(child,parent) {
	for(var property in parent) {
		if (swaf.dummy._swaf_class_keyword.indexOf(property)>=0) continue;
		if (child.prototype[property]) {
			child.prototype['parent$'+property]=parent[property];
			if (parent.CLASSNAME) child.prototype[parent.CLASSNAME.replace(swaf.dummy._swaf_class_regexp,'_')+'$'+property]=parent[property];
		} else {
			child.prototype[property]=parent[property];
		}
	}
};

swaf.$class=function(define) {
	for(var clsName in define) {
		var cls=define[clsName];
		var retObj=function() {
		    if (arguments.length==50 && arguments[49]==2&& arguments[0]==1) return;
			if (this._swaf_event_map_define && swaf.message) {
			    if (this.EVENT_SRC) {
			        if (typeof this.EVENT_SRC == 'string') swaf.event(swaf.$(this.EVENT_SRC),this._swaf_event_map_define);
			        else if (this.EVENT_SRC instanceof RegExp) swaf.event(swaf.$(this.EVENT_SRC),this._swaf_event_map_define);
			        else swaf.event(this.EVENT_SRC,this._swaf_event_map_define);
			    }
				else swaf.event(this,this._swaf_event_map_define);
			}
			for(var i=0;i<this._inherit_initList.length;i++) {
					this[this._inherit_initList[i]].apply(this,arguments);
			}
			if (this.init) this.init.apply(this,arguments);
		};
	    if (cls.BASE) {
	        var baseCls=null;
	        if (cls.BASE instanceof Array) baseCls=cls.BASE[0];
	        else baseCls=cls.BASE;
	        retObj.prototype=new baseCls(1,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,2);
            baseCls=null;                            
        }
		for(var property in cls) {retObj.prototype[property]=cls[property];}
		retObj.prototype.CLASSNAME=cls.NAMESPACE?cls.NAMESPACE.NAMESPACE+'.'+clsName:clsName;
		if (!cls.BASE) cls.BASE=swaf.dummy._swaf_base_class;
		// process extend
		{
			var extList=cls.BASE;
			if (extList instanceof Array && extList.length>1) {
				for(var i=0;i<extList.length;i++) {
					swaf.dummy._swaf_process_class_inherit(retObj,extList[i]);
				}
			} else {
				swaf.dummy._swaf_process_class_inherit(retObj,extList);
			}
			delete cls.BASE;
		}
		if (cls.EXTEND) {
			var extList=cls.EXTEND;
			if (extList instanceof Array && extList.length>1) {
				for(var i=0;i<extList.length;i++) {
					swaf.dummy._swaf_process_class_extend(retObj,extList[i]);
				}
			} else {
				swaf.dummy._swaf_process_class_extend(retObj,extList);
			}
			delete cls.EXTEND;
		}
		if (cls.EVENT_MAP && swaf.message) {
			retObj.prototype._swaf_event_map_define={};
			for(var msg in cls.EVENT_MAP) {
				var item=cls.EVENT_MAP[msg];
				if (item instanceof Array) {
					retObj.prototype._swaf_event_map_define[msg]=[];
					for(var i=0;i<item.length;i++) {
						retObj.prototype._swaf_event_map_define[msg].push(retObj.prototype[item]);
					}
				} else {
					retObj.prototype._swaf_event_map_define[msg]=retObj.prototype[item];
				}
				item=null;
			}
			delete cls.EVENT_MAP;
		}

		retObj.prototype.toString=function() {return this.CLASSNAME;};

	    var singletonObj=null;
		if (typeof cls.SINGLETON !='undefined') {
		    if (cls.SINGLETON==true) {
		        singletonObj={scope:'page',lazyInit:false};
		    } else if (typeof cls.SINGLETON == 'object') { singletonObj=cls.SINGLETON;}
		    if (singletonObj) {
		        retObj.prototype._singleton_info=singletonObj;
		    }
		    delete cls.SINGLETON;
		}

		if (cls.NAMESPACE) {
			cls.NAMESPACE[clsName]=retObj;
			delete cls.NAMESPACE;
		} else {
			window[clsName]=retObj;
		}
		
        if (singletonObj && singletonObj.lazyInit==false) swaf.factory.get(retObj.prototype.CLASSNAME);
		
		retObj=null;
	}
};
if (typeof $class== 'undefined') var $class=swaf.$class;
if (typeof $factory== 'undefined') var $factory=swaf.factory;
swaf.listener(window,"unload",swaf.factory.unloadPage);